<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 原型与原型链
      // 所有的函数都有原型对象（显式原型）--prototype
      // 所有的对象都有原型（隐式原型）--- __proto__
      // 原型链基于一个等式：  所有对象的隐式原型 ==== 创建这个对象的构造函数的显示原型

      const num = 1; // 这句话在js的底层就是 new Number(1)
      console.log(num.__proto__ === Number.prototype);
      const arr = []; // 在js的底层就是 new Array()
      console.log(arr.__proto__ === Array.prototype);

      // 原型链： 就是对象属性的查找机制 --- 顺着原型链逐级往上查找
      // arr.pushaaaa(1)  这句话要报错，js的底层会经历几个阶段，逐级往上不断的查找，直到顶级的null属性结束
      console.log(arr); // 在arr上面找不到
      console.log(arr.__proto__); // 就是arr.__proto__ 上面找这个方法，如果在这里还找不到，继续往上
      console.log(arr.__proto__.__proto__); // 如果这个对象上面找到了就用这个方法，找不到就继续往上
      console.log(arr.__proto__.__proto__.__proto__);
      // console.log(arr.__proto__.__proto__.__proto__.__proto__);

      // 因为__proto__ 这个属性不是一个标准属性， 不同的浏览器对它的实现不一样， 谷歌浏览器里面 [[Prototype]], 火狐里面<prototype>, 所以我们在写原型链的时候，尽量避免使用 __proto__
      console.log(Array.prototype);
      console.log(Array.prototype.__proto__ === Object.prototype);
      console.log(Object.prototype);
      console.log(Object.prototype.__proto__ === null);

      // 下面fn是一个函数，但是从js的大方向来看，他也是一个对象，js里面万物皆对象。
      // 下面的函数在js的底层可以看做是  new Function()
      function fn(a, b) {}
      // console.log(fn.name, fn.length);
      // console.dir(fn);

      const obj = {};
      // console.dir(obj);
    </script>
  </body>
</html>
